<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CRC16 Calculator</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }

        .container {
            max-width: 600px;
            margin: 0 auto;
            text-align: center;
        }

        input[type="file"] {
            margin: 20px 0;
        }

        .result {
            margin-top: 20px;
            font-weight: bold;
        }
    </style>
</head>
<body>

<div class="container">
    <h1>CRC16 Calculator</h1>
    <input type="file" id="fileInput"/>
    <div class="result" id="result"></div>
</div>

<script>
    // Convert hex string to byte array
    function unhexlify(hex) {
        let str = hex.replace(/ /g, '');
        let arr = [];
        for (let i = 0; i < str.length; i += 2) {
            arr.push(parseInt(str.substr(i, 2), 16));
        }
        return arr;
    }

    // CRC16 Zero calculation (with reversed bits and little-endian)
    function crc16Zero(s) {
        const polynomial = 0x18005; // Correct polynomial for CRC16
        const initCrc = 0x0000;
        const xorOut = 0x0000;

        // Generate CRC function without bit reversal
        const crcFun = mkCrcFun(polynomial, false, initCrc, xorOut);

        // Calculate CRC and format output
        return getCrcValue(s, crcFun);
    }

    // Get the CRC value from the string and CRC function
    function getCrcValue(s, crc16) {
        let data = s.replace(' ', '');  // Remove spaces from the input string
        let crcOut = crc16(unhexlify(data));  // Calculate CRC
        let crcHex = (crcOut & 0xffff).toString(16).toUpperCase();  // Convert CRC to hex string

        // Ensure the result is at least 4 characters long, adding leading zeros if necessary
        while (crcHex.length < 4) {
            crcHex = '0' + crcHex;
        }

        // Check the format (you could also explicitly ensure it's lowercase)
        return parseInt(crcHex, 16);
    }


    // CRC function using polynomial and other parameters (bit reversal)
    function mkCrcFun(polynomial, rev, initCrc, xorOut) {
        return function (data) {
            let crc = initCrc;

            for (let i = 0; i < data.length; i++) {
                let byte = data[i];
                if (rev) byte = reverseBits(byte); // Bit reversal if needed
                for (let bit = 7; bit >= 0; bit--) {
                    let bitValue = (byte >> bit) & 1;
                    let xor = ((crc >> 15) & 1) ^ bitValue;
                    crc = (crc << 1) & 0xFFFF;
                    if (xor) {
                        crc = crc ^ polynomial;
                    }
                }
            }
            return crc ^ xorOut;
        };
    }

    // Reverse bits in a byte (8 bits)
    function reverseBits(byte) {
        let rev = 0;
        for (let i = 0; i < 8; i++) {
            rev = (rev << 1) | (byte & 1);
            byte >>= 1;
        }
        return rev;
    }

    // Handle file upload and calculate CRC16
    document.getElementById('fileInput').addEventListener('change', function (event) {
        const file = event.target.files[0];
        if (file) {
            const reader = new FileReader();
            reader.onload = function (e) {
                const fileContent = e.target.result;
                // Convert file content to a hex string
                const hexString = Array.from(new Uint8Array(fileContent))
                    .map(byte => byte.toString(16).padStart(2, '0'))
                    .join(' ');
                // Call crc16Zero function and display the result
                const crcValue = crc16Zero(hexString);
                document.getElementById('result').textContent = `CRC16 Value: 0x${crcValue.toString(16).toUpperCase()}`;
            };
            reader.readAsArrayBuffer(file);  // Read file as binary
        }
    });
</script>

</body>
</html>
